using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public enum PlayerState
{
    Run,
    Idle,
    Jump,
    Attack,
    Falling,
    GetHit,
    Hooking,
    HookingAttack
}


public class PlayerCharacter : MonoBehaviour
{
    public static PlayerCharacter Instance { get; private set; }

    public event EventHandler OnSkillHookActivated;
    public event EventHandler<OnPlayerLandedEventArgs> OnPlayerLanded;
    public event EventHandler<OnPlayerSpeedChangedEventArgs> OnPlayerSpeedChanged;
    public event EventHandler OnPlayerAttack;
    public event EventHandler OnPlayerHooking;
    public event EventHandler OnPlayerJump;
    public event EventHandler OnPlayerGetHit;

    public event EventHandler Audio_OnPlayerAttack;
    public event EventHandler Audio_OnPlayerHitted;
    public event EventHandler Audio_OnCarDead;

    //public event EventHandler OnScoreAdd;

    public class OnPlayerLandedEventArgs : EventArgs
    {
        public bool isGround;
    }
    public class OnPlayerSpeedChangedEventArgs : EventArgs 
    {
        public float speed;
    }

    
    [SerializeField] private PlayerState state;
    [SerializeField] private int hp;//实时血量
    [SerializeField] private float speed = 3;//移动速度
    [SerializeField] private float jumpSpeed = 8;//跳跃速度
    [SerializeField] private int maxHp = 20;//角色最大血量
    [SerializeField] private ValidateHookSkillActivated hook;
    [SerializeField] private PlayerAnimation playerAnimation;
    [SerializeField] private PlayerController controller;//键盘控制器
    [SerializeField] private AudioSource walkAudioSource;

    private Rigidbody2D rigid;

    private Transform checkGround;

    private float originXspeed;//用来保存角色原来的x方向速度。

    private  bool hookFlag = false;//是否发动钩子技能

    private bool jump = false;//判断是否跳起
    
    private bool isGround = false;

    
    //失去控制时间（物理帧）用于生效弹飞
    private float outControlTime = 0;

    private void Awake()
    {
        Instance = this;
    }

    private void Start()
    {
        CountDown.Instance.OnTimerUp += Timer_OnTimerUp;
        
        playerAnimation.OnPlayerAnimationStateChanged += PlayerAnimation_OnPlayerAnimationStateChanged;
        controller.OnJumpAction += Controller_OnJumpAction;
        controller.OnAttackAction += Controller_OnAttackAction;
        controller.OnHookAction += Controller_OnHookAction;

        rigid = GetComponent<Rigidbody2D>();

        state = PlayerState.Idle;

        checkGround = transform.Find("CheckGround");//在脚本所在游戏物体中寻找
        
        hp = maxHp;
    }

    private void Controller_OnHookAction(object sender, EventArgs e)
    {
        //避免二次钩锁
        if (!hook.IsCarHooked())
        {

            CountDown.Instance.ReCounting();
            ActivateHook();//一些触发钩锁技能所需要设置的变量
        }
    }

    private void Controller_OnAttackAction(object sender, EventArgs e)
    {
        if (!GameManager.Instance.IsGameOver())
        {
            OnPlayerAttack?.Invoke(this, EventArgs.Empty);
        }
        
    }

    private void Controller_OnJumpAction(object sender, EventArgs e)
    {
        jump = true;
    }


    // Update is called once per frame
    private void Update()
    {
        PlayerBaseMovement();

        
        if (!IsAtThisPlayerState(PlayerState.GetHit))
        {
            PlayerSkills();
        }

    }
    private void FixedUpdate()//刚体的移动在Fixed Update中调用更好
    {
        CheckGround();
        if (!IsAttacking() && !IsAtThisPlayerState(PlayerState.Hooking))
        {
            rigid.velocity = new Vector2(originXspeed, rigid.velocity.y);//避免横向移动时攻击带有x方向的速度
            Move(controller.GetInputAxisValue());
        }
       
        jump = false;
        outControlTime--;
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.transform.GetComponent<Car>() != null)
        {
            Car tempCar = collision.transform.GetComponent<Car>();
            if(state != PlayerState.Hooking && state != PlayerState.HookingAttack) 
            {
                if (tempCar.GetCarSide() == CarSide.Right)
                {
                    GetHit(1, CarSide.Right);
                }
                if (tempCar.GetCarSide() == CarSide.Left)
                {
                    GetHit(1, CarSide.Left);
                }
            }
        }
    }

    private void PlayerAnimation_OnPlayerAnimationStateChanged(object sender, PlayerAnimation.OnAnimationStateChangedEventArgs e)
    {
        state = e.state;
    }


    #region PLAYER BASE MOVEMENT

    private void PlayerBaseMovement()
    {

        //更新动画状态
        OnPlayerLanded?.Invoke(this, new OnPlayerLandedEventArgs
        {
            isGround = this.isGround
        });

        OnPlayerSpeedChanged?.Invoke(this, new OnPlayerSpeedChangedEventArgs
        {
            speed = Mathf.Abs(controller.GetInputAxisValue())//取方向的绝对值，获取方向大小，设定为速度
        });
        if (state == PlayerState.Run && isGround)
        {
            if (!walkAudioSource.isPlaying)
            {
                walkAudioSource.Play();
            }

        }
        else
        {
            walkAudioSource.Stop();
        }


        if (hp <= 0)
        {
            OnDie();
        }

    }
    private void OnDie()
    {
        GameManager.Instance.GameOver();
    }


    #endregion

    #region PLAYER SKILLS

    private void PlayerSkills()
    {        
        
        #region Active Skills
        //不能直接获取控制器中的按键信息，Hook中的判断条件满足且按下按键时才能触发钩子技能
        if (hookFlag && !IsAtThisPlayerState(PlayerState.GetHit) && hook.CanBeActivated())//受击状态不能触发钩子技能
        {
            Skill_Hook();
        }
        //Debug.Log("PlayerState :"+state);
        if (IsAtThisPlayerState(PlayerState.HookingAttack))
        {
            CountDown.Instance.ReCounting();
        }
        #endregion

        #region Passive Skills
        //随机函数随机发动角色被动技能
        #endregion
    }


    //钩子技能
    private void Skill_Hook()
    {
        OnPlayerHooking?.Invoke(this, EventArgs.Empty);//设置钩子动画启动

        //朝着汽车移动
        this.transform.position = Vector2.MoveTowards(this.transform.position, hook.CarDestinationPoint(), 0.2f);
        hook.SetCarHooked();

        OnSkillHookActivated?.Invoke(this, EventArgs.Empty);

        rigid.gravityScale = 0;//重力调为0，效果是在空中静止
        rigid.velocity = new Vector2(0, 0);//将角色本身的动量清空

        //技能失效倒计时
        
        if (CountDown.Instance.IsTimerIdle())
        {
            CountDown.Instance.StartCount();
        }


        //float distance = hook.GetDistanceToCar(transform.position);
        
        if (hook.GetDistanceToCar(transform.position))
        {
            InactiveHook();
        }

    }

    public void PlayAttackAudio()
    {
        Audio_OnPlayerAttack?.Invoke(this, EventArgs.Empty);
    }

    private void Timer_OnTimerUp(object sender, EventArgs e)
    {        
        HookRecover();
    }

    /*private void PlayerCharacter_OnCarDead(object sender, EventArgs e)
    {
        OnScoreAdd?.Invoke(this, EventArgs.Empty);
        TimeController._instance.NormaliseTime();
        hookFlag = false;
        rigid.gravityScale = 1f;
    }*/

    public void OnCarDead()
    {
        Audio_OnCarDead?.Invoke(this, EventArgs.Empty);
        TimeController._instance.NormaliseTime();
        hookFlag = false;
        rigid.gravityScale = 1f;
    }

    #endregion

    #region PLAYER BASE MOVEMENT ASSISTANT FUNCTIONS

    //判断角色是否在攻击，且在钩锁状态下的攻击
    private bool IsAttacking()
    {
        AnimatorStateInfo asi = playerAnimation.GetAnimationState();
        originXspeed = rigid.velocity.x;
        rigid.velocity = new Vector2(0, rigid.velocity.y);
        //IsName判断当前动画名称
        return asi.IsName("Attack1") || asi.IsName("Attack2") || asi.IsName("Attack3") || asi.IsName("HookAttack1") || asi.IsName("HookAttack2") || asi.IsName("HookAttack3");
    }

    //角色的移动脚本
    private void Move(float h)
    {
        if (outControlTime > 0)
        {
            return;
        }
        Flip(h);
        float vy = rigid.velocity.y;
        if (jump && isGround)
        {
            OnPlayerJump?.Invoke(this, EventArgs.Empty);
            vy = jumpSpeed;
        }
        rigid.velocity = new Vector2(h * speed, vy);

    }

    //判断角色是否在地面
    private void CheckGround()
    {
        isGround = Physics2D.OverlapCircle(checkGround.position, 0.1f, ~LayerMask.GetMask("Player"));//对除了player层的所有层有效，
    }
    
    //使角色翻转
    private void Flip(float h)
    {
        Vector3 scaleLeft = new Vector3(1, 1, 1);
        Vector3 scaleRight = new Vector3(-1, 1, 1);

        if (h > 0.1f)
        {
            transform.localScale = scaleRight;
        }
        else if (h < -0.1f)
        {
            transform.localScale = scaleLeft;
        }
    }

    //角色受伤方法
    private void GetHit(int damage, CarSide carSide)
    {
        Audio_OnPlayerHitted?.Invoke(this, EventArgs.Empty);
        isGround = false;
        rigid.gravityScale = 1;
        hp -= damage;
        if (hp < 0) { hp = 0; }

        UIManager.Instance.setPlayerHp(hp, maxHp);

        //受伤动画
        OnPlayerGetHit?.Invoke(this, EventArgs.Empty);

        //受击朝反方向飞出
        Vector2 force = new Vector2(3, 6);
        if (carSide == CarSide.Right)
        {
            force.x *= -8;
        }
        if (carSide == CarSide.Left)
        {
            force.x *= 8;
        }

        rigid.velocity = force;
        outControlTime = 30;
    }

    //辅助球，辅助查看状态
    private void OnDrawGizmos()
    {
        if (Application.isPlaying)//Gizmos.DrawSphere在编辑状态下也能运行，添加游戏是否运行的判断
        {
            Gizmos.color = Color.white;
            if (isGround)
            {
                Gizmos.color = Color.red;
            }
            Gizmos.DrawSphere(checkGround.position, 0.1f);//该函数在编辑状态下也能执行
        }
        //Gizmos.DrawLine(hook.car.position, transform.position);

    }


    public bool IsAtThisPlayerState(PlayerState state)
    {
        switch (state)
        {
            default:
            case PlayerState.GetHit:
                return this.state == state;
            case PlayerState.Attack:
                return this.state == state;
            case PlayerState.HookingAttack:
                return this.state == state;
            case PlayerState.Hooking:
                return this.state == state;
            case PlayerState.Falling:
                return this.state == state;
            case PlayerState.Idle:
                return this.state == state;
            case PlayerState.Jump:
                return this.state == state;
            case PlayerState.Run:
                return this.state == state;
        }
    }
    #endregion

    #region PLAYER SKILLS ASSISTANT FUNCTIONS
    
    //恢复钩子状态的角色时空状态
    private void HookRecover()
    {
        TimeController._instance.NormaliseTime();
        hookFlag = false;
        rigid.gravityScale = 1;
    }

    //启动钩子技能
    private void ActivateHook()
    {
        hookFlag = true;
        isGround = true;
        jump = false;
    }

    //关闭钩子技能
    private void InactiveHook()
    {
        hookFlag = false;
    }


    #endregion

}

